import 'dart:io';

import 'convert.dart';
import 'lib/common/config/request_config.dart';

const String request_page = "lib/common/network/request.dart";
const String request_api_page = "lib/common/network/network.api.dart";
const String request_config = 'lib/common/config/request_config.dart';
const String model_page = "lib/common/model/";

void main() {
  // _test();
  // _start();
  // print(_capitalize(_res));
  // print(_pathName(_capitalize(_res)));
  // String str = "/joinApply/subordinateList/:id=";
  // final className = RegExp(r"(?<=/)\w*(?=((/(:)|\?)\w*=))").stringMatch(str);
  // print(className);
  _start();
}

void _start() {
  String api = '''
part of 'network.dart';

abstract class API {
 ''';
  String request = '';
  String requestBody = '';
  String importRequest = '';
  String apiBody = '';
  for (var element in request_content) {
    final String? _model = element["response"]?["success"]?["raw"];
    String? _url = element["request"]?["url"];
    final String? _method = element["method"];
    final String _urlDesc = element['name'] ?? '';
    if (_model == null || _url == null || _method == null) {
      return;
    }
    if (_url[_url.length - 1] != "/") _url += "/";
    if (!_url.contains(":")) _url += ":type";
    if (_model != "") _writeModel(_model, _url);
    apiBody += _writeAPI(_url, _urlDesc);
    final className = RegExp(r"(?<=/)\w*(?=((/(:)|\?)\w*))").stringMatch(_url);
    final _fileName = _pathName(_capitalize(className) + "_model.dart");
    final _tempReq = _writeRequest(_url, _method, _urlDesc, element);
    if (!_tempReq.contains("static Future<void>")) {
      importRequest += "import 'package:oster_cigarette/common/model/$_fileName';\n";
    }
    requestBody += _tempReq;
    print("$_url, $className");
  }
  request = '''
$importRequest
import 'package:oster_cigarette/common/network/network.dart';
abstract class Request {
$requestBody''';
  final File apiFile = File(request_api_page);

  final File requestFile = File(request_page);
  if (!requestFile.existsSync()) {
    request += "}";
  } else {
    // 方法追加到请求中
    String reqContent = requestFile.readAsStringSync();
    final String _importRequest = RegExp(r"import(\w|\W)*(?=abstract)").stringMatch(reqContent)!;
    importRequest += _importRequest;
    reqContent = reqContent.replaceFirst(RegExp(r"import(\w|\W)*(?=abstract)"), importRequest);
    request = reqContent.replaceFirst(RegExp(r"(?<=abstract class Request {)"), "\n$requestBody");
  }
  if (!apiFile.existsSync()) {
    api += apiBody;
    api += "}";
  } else {
    String reqApi = apiFile.readAsStringSync();
    api = reqApi.replaceFirst(RegExp(r"}"), apiBody + "}");
  }

  apiFile.writeAsStringSync(api);
  apiFile.createSync();
  requestFile.writeAsStringSync(request);
  requestFile.createSync();
  final File requestConfigFile = File(request_config);
  requestConfigFile.writeAsStringSync("const List<Map<String, dynamic>> request_content = [];");
  requestConfigFile.createSync();
}

/// 写模型
void _writeModel(String model, String url) {
  const String path = model_page;
  final _d = Directory(path);
  if (!_d.existsSync()) {
    Directory(path).createSync();
  }
  final className = RegExp(r"(?<=/)\w*(?=((/(:)|\?)\w*))").stringMatch(url);
  final _res = Convert().convert(content: model, className: _capitalize(className) + "Response");
  final _fileName = _pathName(_capitalize(className) + "_model.dart");
  final File file = File(path + _fileName);
  if (file.existsSync()) return;
  file.writeAsStringSync(_res);
  file.createSync();
}

/// 写接口
String _writeAPI(String url, String urlDesc) {
  final className = RegExp(r"(?<=/)\w*(?=((/(:)|\?)\w*))").stringMatch(url);
  final classInterPath = RegExp(r"[/\w]*(?=(\?|:))").stringMatch(url);
  String apiName = '''
  // $urlDesc
  static const String $className = "$classInterPath";
''';
  return apiName;
}

/// 写请求
String _writeRequest(String url, String method, String urlDesc, Map<String, dynamic> sender) {
  final className = RegExp(r"(?<=/)\w*(?=((/(:)|\?)\w*))").stringMatch(url);
  String paramsContent = "";
  String requestJsonBody = "";
  String paramsMethod = "";
  String paramsDesc = "";
  final params = sender['request'];
  final List<dynamic> _getParams = params["resful"]?["parameter"]!;
  if (_getParams.isNotEmpty) {
    paramsMethod = "params: {";
    paramsDesc = "// ";
    paramsContent = "{";
    for (var element in _getParams) {
      final String? _p = RegExp(r"\w*").stringMatch(element["key"]!);
      // final String type = element["field_type"]! == "String" ? "String" : "int";
      const String type = "String";
      if (_p != null) {
        paramsContent += "$type? $_p, ";
        paramsMethod += '"$_p": $_p, ';
        paramsDesc += "$_p:${element["description"]}, ";
      }
    }
    paramsMethod += "}";
    paramsContent += "}";
  } else {
    final List<dynamic> _getParams2 = params["body"]?["raw_para"]!;
    if (params["body"]?["model"] != "application/json") {
      requestJsonBody = ", jsonBody: false";
    }
    if (_getParams2.isNotEmpty) {
      paramsDesc = "// ";
      paramsContent = "{";
      paramsMethod = "params: {";
      for (var element in _getParams2) {
        final String? _p = RegExp(r"\w*").stringMatch(element["key"]!);
        // final String type = element["field_type"]! == "String" ? "String" : "int";
        const String type = "String";
        if (_p != null) {
          paramsContent += "$type? $_p, ";
          paramsMethod += '"$_p": $_p, ';
          paramsDesc += "$_p:${element["description"]}, ";
        }
      }
      paramsMethod += "}";
      paramsContent += "}";
    }
  }
  String returnType = _capitalize(className) + "Response";
  String returnName = 'return ${_capitalize(className) + "ResponseExt"}.fromJson(res);';
  if (sender["response"]!["success"]["raw"] == "") {
    returnName = "return;";
    returnType = "void";
  }
  if (paramsMethod != "") paramsMethod += ", ";
  String apiName = '''
  // $urlDesc
  $paramsDesc
  static Future<$returnType> $className($paramsContent) async {
    final res = await NetworkTool.request(API.$className, ${paramsMethod}method: HTTPMETHOD.$method);
    $returnName
  }
''';
  return apiName;
}

String _capitalize(String? sender) {
  if (sender == null) return "Response";
  return "${sender[0].toUpperCase()}${sender.substring(1)}";
}

String _pathName(String className) {
  final RegExp exp = RegExp(r'(?<=[a-z])[A-Z]');
  return className.replaceAllMapped(exp, (Match m) => '_${m.group(0)}').toLowerCase();
}
